package com.danicsoft.daide.command;

import java.util.NoSuchElementException;

import com.danicsoft.daide.token.TokenGroup;


/**
 * The generalized class for any type of command that can be sent to the server
 * as a query (as a command with no parameters, eg MDF). This class takes care
 * of the reading and writing necessary for these types of commands.
 * 
 * @author Daniel Yule (daniel.yule@gmail.com)
 * @version 1.0
 */
public abstract class QueryableCommand extends Command {

	/**
	 * Whether or not this instance is a querying command. If not, it contains
	 * information in erpsonse to a query, implicit or explicit.
	 */
	private boolean isQuery;

	/**
	 * Construct a new <code>QueryableCommand</code> from the tokens
	 * specified. If there are no tokens left in the given group, then it will
	 * be assumed that this is a query. Otherwise, this can be assumed to be a
	 * response to a query.
	 * 
	 * @param tokens
	 *        The tokens to load from.
	 * @throws ParseException
	 *         If there was a problem reading from the given tokens.
	 */
	public QueryableCommand(TokenGroup tokens) throws ParseException {
		super(tokens);
	}

	/**
	 * Creates a new <code>QueryableCommand</code> to be used as a query to
	 * send to the server.
	 */
	public QueryableCommand() {
		this(true);
	}

	/**
	 * Construct a new <code>QueryableCommand</code> which can be either a
	 * Query Command or not, depending on the boolean argument.
	 * 
	 * @param isQuery
	 *        True if this is to be a query, false if it is a response.
	 */
	protected QueryableCommand(boolean isQuery) {
		this.isQuery = isQuery;
	}

	public final void doIO(TokenIO tokenIO, TokenGroup tokens) throws ParseException {
		if (isQuery)
			return;
		try {
			doNonQueryIO(tokenIO, tokens);
		}
		catch (NoSuchElementException e) {
			isQuery = true;
		}

	}

	/**
	 * Do the IO necessary if this is not a Query. If it is a query, the IO has
	 * already been taken care of.
	 * 
	 * @param tokenIO
	 *        The object to use to do the IO with.
	 * @param tokens
	 *        The TokenGroup to read or write to.
	 * @throws ParseException
	 *         If there was a problem reading from the tokens.
	 */
	protected abstract void doNonQueryIO(TokenIO tokenIO, TokenGroup tokens) throws ParseException;

	@Override
	public void initialize() {
		isQuery = false;
		super.initialize();
	}

	/**
	 * Gets whether or not this command is a query.
	 * 
	 * @return True if this is a query, false otherwise.
	 */
	public boolean isQuery() {
		return isQuery;
	}

}
